package com.rtx.edi.platform.config.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rtx.api.utils.FastJsonUtils;
import com.rtx.api.utils.MultipleDataSource;
import com.rtx.edi.model.api.dto.PlApiMappingConfigDTO;
import com.rtx.edi.model.api.po.PlApiMappingConfig;
import com.rtx.edi.platform.baseinfo.mapper.PlApibaseinfoMapper;
import com.rtx.edi.platform.config.bean.CheckRule;
import com.rtx.edi.platform.config.bean.ConfigRule;
import com.rtx.edi.platform.config.bean.PreActive;
import com.rtx.edi.platform.config.bean.RowCheckRule;
import com.rtx.edi.platform.config.mapper.PlApiMappingConfigMapper;
import com.rtx.edi.platform.config.service.PlApiMappingConfigService;
import com.rtx.edi.platform.handler.mapper.HandleSqlMapper;
import com.rtx.edi.platform.mapping.mapper.PlApiMappingMapper;

import cn.hutool.json.JSONUtil;

@Service
public class PlApiMappingConfigServiceImpl  extends ServiceImpl<PlApiMappingConfigMapper, PlApiMappingConfig> implements PlApiMappingConfigService{

	@Autowired
	PlApiMappingMapper plApiMappingMapper;
	
	@Autowired
	PlApibaseinfoMapper plApibaseinfoMapper;
	
	@Autowired
	PlApiMappingConfigMapper plApiMappingConfigMapper;
	
	@Autowired
	HandleSqlMapper handleSqlMapper;
	
	
	@Override
	public void selectPlApiMappingConfigList(Page<PlApiMappingConfig> pageParam, PlApiMappingConfig qcd) {
		LambdaQueryWrapper<PlApiMappingConfig> query = Wrappers.lambdaQuery();
        query
        .eq(PlApiMappingConfig::getApiMappingId, qcd.getApiMappingId())
        .orderByAsc(PlApiMappingConfig::getId);
        if(qcd != null){
//            //公司编号、公司名称、公司类型、公司状态
//        	if(StringUtils.hasText(qcd.getQueryName())) {
//        		query.like(PlApiMappingConfig::getQueryName, qcd.getQueryName());
//        	}
        }
        baseMapper.selectPage(pageParam,query);
	}

	@Override
	public List<PlApiMappingConfig> queryByMappingId(PlApiMappingConfigDTO dto) {
		LambdaQueryWrapper<PlApiMappingConfig> qw = Wrappers.lambdaQuery();
		qw.eq(PlApiMappingConfig::getApiMappingId, dto.getApiMappingId());
		return baseMapper.selectList(qw);
	}

	@Override
	public Map<String,Map<String,Object>> executeSqlByMappingId(Long plApiMappingId,String requestStr) {
		//查询配置的sql信息
		LambdaQueryWrapper<PlApiMappingConfig> qw = Wrappers.lambdaQuery();
		qw.
		eq(PlApiMappingConfig::getApiMappingId, plApiMappingId).
		orderByDesc(PlApiMappingConfig::getSequence);
		List<PlApiMappingConfig> list = baseMapper.selectList(qw);
		
		Map<String,Map<String,Object>> executeSqlResult = executeSqlByMappingId(list, requestStr);
		return executeSqlResult;
	}
	
	public Map<String,Map<String,Object>> executeSqlByMappingId(List<PlApiMappingConfig> list,String requestStr) {
		//执行查询sql后的全局变量
		Map<String,Map<String,Object>> globalMap = new HashMap<String, Map<String,Object>>();
		//校验规则执行后结果集合
		Map<String,Object> checkRuleResultMap = new HashMap<String, Object>();
		//将判断条件写入全局变量
		globalMap.put("RTX校验规则集合", checkRuleResultMap);
	
		
		for(int i =0; i<list.size();i++) {
			PlApiMappingConfig config = list.get(i);
			//配置数据源
			configDataSource(globalMap,i,requestStr);
			
			//处理前置校验
			//STOP 为终止该配置项 继续执行
			//CONTINUE 为继续执行该配置项目
			String preActive = handlePreActive(config,checkRuleResultMap);
			if("STOP".equals(preActive)) {
				continue;
			}
			
			//执行查询sql结果集
			List<Map<String,Object>> queryResultList =	handleQueryconfig(config,globalMap,requestStr);
			
			//执行校验规则逻辑
			checkRule(queryResultList,config,checkRuleResultMap);
			
			//执行 结果行校验规则
			rowCheckRule(queryResultList,config,checkRuleResultMap);
			
			MultipleDataSource.ClearDataSourceKey();
		}
		
		MultipleDataSource.ClearDataSourceKey();
		return globalMap;
	}
	
	private void configDataSource(Map<String,Map<String,Object>> globalMap,int index,String requestStr) {
		String whseid = Optional.ofNullable((String) JSONUtil.parse(requestStr).getByPath("whseid")).orElse("").toLowerCase();
		if(!(whseid.startsWith("enterprise")||whseid.startsWith("wmwse"))) {
			if(0==index) {
				whseid = "enterprise";
			}else {
				whseid = (String)globalMap.get("whseid").get("whseid");
			}
		}
		
		MultipleDataSource.setDataSourceKey(whseid);
	}
	
	/**
	 * 处理前置校验
	 * STOP 为终止该配置项 继续执行
	 * CONTINUE 为继续执行该配置项目
	 * 
	 */
	private String handlePreActive(PlApiMappingConfig config,Map<String,Object> checkRuleResultMap) {
		String handleResult = "CONTINUE";
		//前置执行条件
		if(StringUtils.hasLength(config.getPreActive())) {
			List<PreActive> preActiveList = JSON.parseArray(config.getPreActive(),PreActive.class);
			List<String> preActiveStatusList = new ArrayList<String>();
			for(PreActive preActive:preActiveList) {
				String ruleStatus = String.valueOf(checkRuleResultMap.get(preActive.getRuleName())) ;
				if(ruleStatus.equals(preActive.getActiveStatus())) {
					preActiveStatusList.add("true");
				}else {
					preActiveStatusList.add("false");
				}
			}
			if(preActiveStatusList.contains("false")) {
				handleResult = "STOP";
			}
		}
		return handleResult;
	}
	
	/**
	 * 执行查询sql结果集
	 * @param apiMappingConfig
	 * @param executeSqlResult
	 * @param requestStr
	 */
	private List<Map<String,Object>> handleQueryconfig(PlApiMappingConfig config,Map<String,Map<String,Object>> executeSqlResult,String requestStr) {
//		QueryConfig config = JSON.parseObject(apiMappingConfig.getQueryConfig(), QueryConfig.class);
		
		//查询条件值对于源报文父节点
		String queryRoot = config.getQueryRoot();
		//查询名称
		String queryName = config.getQueryName();
		
		String sourceRequestNodeData = FastJsonUtils.queryByParentNode(requestStr, queryRoot);
		
		int type = FastJsonUtils.resolveJSONRootType(sourceRequestNodeData);
		
		List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>();
		
		if(1 == type) {
			//执行sql并将数据写入到全局变量
			resultList = executeQuerySql(config,executeSqlResult,sourceRequestNodeData);
		}else if(2==type){
			List<String> querycolumnMainDataList = JSON.parseArray(sourceRequestNodeData,String.class);
			for(String querycolumnMainData:querycolumnMainDataList) {
				//执行sql并将数据写入到全局变量
				resultList.addAll(executeQuerySql(config,executeSqlResult,querycolumnMainData));
			}
		}else {
			throw new RuntimeException("查询名称-"+queryName+"-queryRoot-"+queryRoot+"在源报文中为叶子节点");
		}
		return resultList;
	}
	

	/**
	 * 执行查询并将查询结果放到全局变量
	 * @param config
	 * @param executeSqlResult
	 * @param sourceRequestNodeData
	 * @return 查询结果集
	 */
	private List<Map<String,Object>> executeQuerySql(PlApiMappingConfig config,Map<String,Map<String,Object>> executeSqlResult,String sourceRequestNodeData) {
		//查询条件字段 源API报文中获取
		//如：[{"#{sku}":"sku"}]
		String queryColumn = config.getQueryColumn().replace("\\", "").replaceAll("^\"|\"$", "");
		List<JSONObject> queryColumnList = JSON.parseArray(queryColumn,JSONObject.class);
		//查询sql模板
		String querySqlTemplate = config.getQuerySql();
		//查询结果主要字段
		String queryColumnMainValue = config.getQueryColumnMainValue();
		//查询结果 设置到api全局变量中的值
		String queryResultName = config.getQueryResultName();
		
		//源数据
		JSONObject querycolumnMainData =  JSON.parseObject(sourceRequestNodeData);
		
		//替换查询sql模板中变量的值
		String tempSql = new String(querySqlTemplate);
		for(JSONObject querycolumn:queryColumnList) {
			String column = (String) querycolumn.keySet().toArray()[0];
			String queryValue = "'"+Optional.ofNullable(querycolumnMainData.getString(querycolumn.getString(column))).orElse("")+"'";
			String replaceStr = "\\#\\{"+column.trim()+"\\}";
			tempSql = tempSql.replaceAll(replaceStr, queryValue);
		}
		
		//执行查询sql，并将查询结果值 设置到api全局变量中
		List<Map<String,Object>>  queryResultList = handleSqlMapper.select(tempSql);
		for(Map<String,Object> queryResult:queryResultList) {
			if("true".equals(config.getWhsequeryflag())) {
				executeSqlResult.put("whseid", queryResult);
			}else {
				String mainValue = String.valueOf(queryResult.get(queryColumnMainValue));
				String globalDataName = queryResultName+mainValue;
				executeSqlResult.put(globalDataName, queryResult);
			}

		}
		
		//当此sql标记（Whsequeryflag）为true 将此sql设置为后续数据源sql
		//判断仓库号查询获取是否异常
		if("true".equals(config.getWhsequeryflag())) {
			Assert.hasText(String.valueOf(executeSqlResult.get("whseid").get("whseid")), "仓库号获取异常-"+tempSql);
		}
		return queryResultList;
	}
	
	/**
	 * 如校验规则是否存在
	 * 如存在
	 * 1.解析输入校验规则是否有误 须在新增时校验输入校验规则是否有误
	 * 2.解析每条校验规则
	 * 3.根据查询数据结果执行每条校验规则
	 * @param queryResultList
	 * @param config
	 */
	private void checkRule(List<Map<String,Object>>  queryResultList,PlApiMappingConfig config,Map<String,Object> checkRuleResultMap) {
		//判断校验规则是否存在 不存在则直接跳过
		String checkRule = config.getCheckRule();
		if(!StringUtils.hasLength(checkRule)) {
			return;
		}
		
		//解析校验规则 根据查询数据结果执行每条校验规则
		List<CheckRule> rules = JSON.parseArray(checkRule,CheckRule.class);
		for(CheckRule rule:rules) {
			checkRuleByQueryData(rule,queryResultList,checkRuleResultMap);
		}
	
	}
	
	
	//根据查询数据结果执行每条校验规则
	private void checkRuleByQueryData(CheckRule rule,List<Map<String,Object>>  queryResultList,Map<String,Object> checkRuleResultMap){
		String column = rule.getColumn();
		String assertion = Optional.ofNullable(rule.getAssertion()).orElse("stop");
		String condition = Optional.ofNullable(rule.getCondition()).orElse("");
		String msg = rule.getMsg();
		int value = Integer.parseInt(Optional.ofNullable(rule.getValue()).orElse("0"));
		
		//设置校验规则判断状态
		for(Map<String,Object> queryData:queryResultList) {
			
			switch (condition) {
			case "exists":
				if(queryData.containsKey(column)&&StringUtils.hasLength(String.valueOf(queryData.get(column)))) {
					checkRuleResultMap.put(rule.getRuleName(), true);
				}else {
					checkRuleResultMap.put(rule.getRuleName(), false);
					if("stop".equals(assertion)) {
						throw new RuntimeException(msg);
					}
				}
				break;
			case "noexists":
				if(!queryData.containsKey(column) || !StringUtils.hasLength(String.valueOf(queryData.get(column)))) {
					checkRuleResultMap.put(rule.getRuleName(), true);
				}else {
					checkRuleResultMap.put(rule.getRuleName(), false);
					if("stop".equals(assertion)) {
						throw new RuntimeException(msg);
					}
				}
				break;
			case "lt":
				if(queryData.containsKey(column)&&StringUtils.hasLength(String.valueOf(queryData.get(column)))) {
					int queryValue = Integer.parseInt(queryData.get(column)+"");
					if(queryValue < value) {
						checkRuleResultMap.put(rule.getRuleName(), true);
						throw new RuntimeException(msg);
					}else {
						checkRuleResultMap.put(rule.getRuleName(), false);
						if("stop".equals(assertion)) {
							throw new RuntimeException(msg);
						}
					}
				}else {
					throw new RuntimeException("判断规则"+rule.getRuleName()+"执行判断中列"+column+"在查询结果集合中不存在！");
				}
				break;
			case "gt":
				if(queryData.containsKey(column)&&StringUtils.hasLength(String.valueOf(queryData.get(column)))) {
					int queryValue = Integer.parseInt(queryData.get(column)+"");
					if(queryValue > value) {
						checkRuleResultMap.put(rule.getRuleName(), true);
					}else {
						checkRuleResultMap.put(rule.getRuleName(), false);
						if("stop".equals(assertion)) {
							throw new RuntimeException(msg);
						}
					}
				}else {
					throw new RuntimeException("判断规则-"+rule.getRuleName()+"-执行判断中列"+column+"在查询结果集合中不存在！");
				}
				break;
			case "ge":
				if(queryData.containsKey(column)&&StringUtils.hasLength(String.valueOf(queryData.get(column)))) {
					int queryValue = Integer.parseInt(queryData.get(column)+"");
					if(queryValue > value || queryValue == value) {
						checkRuleResultMap.put(rule.getRuleName(), true);
					}else {
						checkRuleResultMap.put(rule.getRuleName(), false);
						if("stop".equals(assertion)) {
							throw new RuntimeException(msg);
						}
					}
				}else {
					throw new RuntimeException("判断规则-"+rule.getRuleName()+"-执行判断中列"+column+"在查询结果集合中不存在！");
				}
				break;
			case "le":
				if(queryData.containsKey(column)&&StringUtils.hasLength(String.valueOf(queryData.get(column)))) {
					int queryValue = Integer.parseInt(queryData.get(column)+"");
					if(queryValue < value || queryValue == value) {
						checkRuleResultMap.put(rule.getRuleName(), true);
					}else {
						checkRuleResultMap.put(rule.getRuleName(), false);
						if("stop".equals(assertion)) {
							throw new RuntimeException(msg);
						}
					}
				}else {
					throw new RuntimeException("判断规则-"+rule.getRuleName()+"-执行判断中列"+column+"在查询结果集合中不存在！");
				}
				break;

			default:
				break;
			}
		}
	}
	
	/**
	 * 查询结果行校验规则
	 */
	private void rowCheckRule(List<Map<String,Object>>  queryResultList,PlApiMappingConfig config,Map<String,Object> checkRuleResultMap) {
		//判断校验规则是否存在 不存在则直接跳过
		String rowCheckRule = config.getRowCheckRule();
		if(!StringUtils.hasLength(rowCheckRule)) {
			return;
		}
		
		RowCheckRule rule = JSON.parseObject(rowCheckRule,RowCheckRule.class);
		
		String condition = Optional.ofNullable(rule.getCondition()).orElse("");
		String msg = rule.getMsg();
		int value = Integer.parseInt(Optional.ofNullable(rule.getValue()).orElse("0"));
		String assertion = Optional.ofNullable(rule.getAssertion()).orElse("stop");
		int rowCount = queryResultList.size();
		
		switch (condition) {
		case "lt":
			if(rowCount<value) {
				checkRuleResultMap.put(rule.getRuleName(), true);
			}else {
				checkRuleResultMap.put(rule.getRuleName(), false);
				if("stop".equals(assertion)) {
					throw new RuntimeException(msg);
				}
			}
			break;
		case "gt":
				if(rowCount > value) {
					checkRuleResultMap.put(rule.getRuleName(), true);
				}else {
					checkRuleResultMap.put(rule.getRuleName(), false);
					if("stop".equals(assertion)) {
						throw new RuntimeException(msg);
					}
				}
			break;
		case "ge":
				if(rowCount > value || rowCount == value) {
					checkRuleResultMap.put(rule.getRuleName(), true);
				}else {
					checkRuleResultMap.put(rule.getRuleName(), false);
					if("stop".equals(assertion)) {
						throw new RuntimeException(msg);
					}
				}
			break;
		case "le":
			if(rowCount < value || rowCount == value) {
				checkRuleResultMap.put(rule.getRuleName(), true);
			}else {
				checkRuleResultMap.put(rule.getRuleName(), false);
				if("stop".equals(assertion)) {
					throw new RuntimeException(msg);
				}
			}
			break;

		default:
			break;
		}
	}
	
//	/**
//	 * 执行更新删除逻辑
//	 * @param apiMappingConfig
//	 * @param executeSqlResult
//	 * @param requestStr
//	 */
//	private void HandleConfigRule(PlApiMappingConfig apiMappingConfig,List<Map<String,Object>>  queryResultList,Map<String,Object> checkRuleResultMap,String requestStr) {
//		String updConfigStr = apiMappingConfig.getConfigRule();
//		if(!StringUtils.hasLength(updConfigStr)) {
//			return;
//		}
//		
//		//    {
//		//    	"handleType": "操作类型 DELETE 或者 UPDATE",
//		//    	"handleSql": "操作sql",
//		//    	"handleColumn": [{
//		//    		"placeholder": "sql占位符",
//		//    		"valueSource": "取值路径",
//		//    		"valueType": "取值来源 request报文 query当前查询结果"
//		//    	}],
//		//    	"preActive": {
//		//    		"ruleName": ["校验规则名称"]
//		//    	}
//		//    }
//		ConfigRule	updConfig = JSON.parseObject(updConfigStr, ConfigRule.class);
//		String preActiveStatus = handleConfigPreActive(updConfig,checkRuleResultMap);
//		if(!"CONTINUE".equals(preActiveStatus)) {
//			return;
//		}
//		
//		JSONObject requestObject = JSONUtil.parseObj("request");
//		
//		for(Map<String,Object> queryRes:queryResultList) {
//			
//		}
//		String handleSql = updConfig.getHandleSql();
//		String handleColumnStr = updConfig.getHandleColumn();
//		List<HandleColumn> list = JSON.parseArray(handleColumnStr, HandleColumn.class);
//		for(HandleColumn handleColumn:list) {
//			String type = handleColumn.getValueType();
//			String replaceValue = "";
//			if("request".equals(type)) {
//				requestObject.getByPath(handleColumnStr);
//			}else {
//				
//			}
//			handleColumn.getPlaceholder();
//			handleColumn.getValueSource();
//		}
//	}
	
	
	/**
	 * 配置前置校验
	 * STOP 为不执行
	 * CONTINUE 为继续执行
	 * 
	 */
	private String handleConfigPreActive(ConfigRule config,Map<String,Object> checkRuleResultMap) {
		String handleResult = "CONTINUE";
		//前置执行条件
		if(StringUtils.hasLength(config.getPreActive())) {
			List<PreActive> preActiveList = JSON.parseArray(config.getPreActive(),PreActive.class);
			List<String> preActiveStatusList = new ArrayList<String>();
			for(PreActive preActive:preActiveList) {
				String ruleStatus = String.valueOf(checkRuleResultMap.get(preActive.getRuleName())) ;
				if(ruleStatus.equals(preActive.getActiveStatus())) {
					preActiveStatusList.add("true");
				}else {
					preActiveStatusList.add("false");
				}
			}
			if(preActiveStatusList.contains("false")) {
				handleResult = "STOP";
			}
		}
		return handleResult;
	}
}
